﻿namespace NTLib.Pipe.Streaming.Formats
{
    using Containers;
    using Core.Pool;
    using Descriptors.Packages;
    using Packages;
    using System;
    using System.IO;

    /// <summary>
    /// Base formater class element of the pool
    /// </summary>
    public abstract class BaseConcurentPackageFormater : PoolItem, IPackageFormater
    {
        #region Fields

        private Guid _id = Guid.NewGuid();

        #endregion

        #region Properties

        /// <summary>
        /// Gets the unique identifier of the component.
        /// </summary>
        public Guid Id
        {
            get { return this._id; }
        }

        /// <summary>
        /// Gets the reader descriptor.
        /// </summary>
        public abstract IPackageDescriptor ReaderDescriptor { get; }

        #endregion

        #region Methods

        /// <summary>
        /// Convert an IPackage structure to a data Structure.
        /// </summary>
        /// <param name="pkg"></param>
        /// <param name="T"></param>
        /// <returns></returns>
        public virtual object FromPackage(IPackage pkg, Type T)
        {
            return ConvertBytesToData(pkg.Stream, T);
        }

        /// <summary>
        /// Convert an IPackage structure to a data Structure.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pkg"></param>
        /// <returns></returns>
        public virtual T FromPackage<T>(IPackage pkg)
        {
            return (T)FromPackage(pkg, typeof(T));
        }

        /// <summary>
        /// Convert the data structure to an IPackage.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns>Return a SimplePackage that contains the data</returns>
        public virtual IPackage ToPackage<T>(T data)
        {
            byte[] dataBytes = ConvertDataToBytes(data, typeof(T));
            SimplePackage pkg = SimplePackage.Create();
            pkg.Stream.Write(dataBytes, 0, dataBytes.Length);
            pkg.Stream.Seek(0, System.IO.SeekOrigin.Begin);

            return pkg;
        }

        /// <summary>
        /// Converts the data to bytes.
        /// </summary>
        protected abstract byte[] ConvertDataToBytes(object data, Type T);

        /// <summary>
        /// Converts the data to bytes.
        /// </summary>
        protected abstract object ConvertBytesToData(Stream data, Type T);

        /// <summary>
        /// Called when the pool item is reset.
        /// Everything MUST be initialized on this method.
        /// </summary>
        protected override void OnReset()
        {
            this._id = Guid.NewGuid();
        }

        #endregion
    }
}
